package com.dean.pokeking.utils

import android.content.Context
import android.net.Uri
import android.util.Log
import com.dean.pokeking.beans.*
import com.google.gson.Gson
import org.apache.poi.ss.usermodel.Sheet
import org.apache.poi.ss.usermodel.WorkbookFactory
import java.io.*

/**
 * @ClassName TODO
 * @Description TODO
 * @Author Dean
 * @Date 2023/3/22
 * @Version 1.0
 */
class FileUtil {
    companion object {

        fun writeMonsterInfoToExcel(context: Context, player: PlayerList, teamName: String) {
            try {
                val fileDir = context.filesDir
                val teamExcelFile = File(fileDir, "excels/$teamName.xlsx")
                val workbook = WorkbookFactory.create(teamExcelFile)
                val sheet = workbook.getSheetAt(0)
                for (i in 1 until sheet.physicalNumberOfRows) {
                    val row = sheet.getRow(i)
                    val id = row.getCell(0).stringCellValue?.trim()?.toInt() ?: 0
                    if (id == 0) continue
                    if (id == player.id) {
                        val outputStream =
                            context.contentResolver.openOutputStream(Uri.fromFile(teamExcelFile))
                        row.createCell(17).setCellValue(player.note)
                        sheet.workbook.write(outputStream)
                        outputStream?.close()
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        fun readAllTeamFromExcel(context: Context, teamName: String): List<NpcInfo> {
            val npcInfoList: MutableList<NpcInfo> = mutableListOf()
            try {
                val fileDir = context.filesDir
                val teamExcelFile = File(fileDir, "excels/$teamName.xlsx")
                val workbook = WorkbookFactory.create(teamExcelFile)
                val sheet = workbook.getSheetAt(0)
                var lineupList: MutableList<LineupList> = mutableListOf()
                var monsterList: MutableList<MonsterList> = mutableListOf()
                for (i in 1 until sheet.physicalNumberOfRows) {
                    val row = sheet.getRow(i)
                    val currentArea = row.getCell(1)?.stringCellValue?.trim()
                    val currentNpc = row.getCell(2)?.stringCellValue?.trim()
                    val currentTeam = row.getCell(3)?.stringCellValue?.trim()
                    val player = PlayerList(
                        id = row.getCell(0)?.stringCellValue?.trim()?.toInt() ?: 0,
                        name = row.getCell(4).stringCellValue?.trim(),
                        firstAttribute = row.getCell(5).stringCellValue?.trim(),
                        secondAttribute = row.getCell(6).stringCellValue?.trim(),
                        characteristic = row.getCell(7).stringCellValue?.trim(),
                        prop = row.getCell(8).stringCellValue?.trim(),
                        skillA = row.getCell(9).stringCellValue?.trim(),
                        skillB = row.getCell(10).stringCellValue?.trim(),
                        skillC = row.getCell(11).stringCellValue?.trim(),
                        skillD = row.getCell(12).stringCellValue?.trim(),
                        note =  row.getCell(17).stringCellValue?.trim()
                    )
                    if (currentArea != null && currentNpc != null && currentTeam != null) {
                        //如果是下一个npc那么就把数据组装起来
                        if (lineupList.isNotEmpty()) {
                            //如果当前npc已经不是之前的npc了的话
                            if (currentNpc != lineupList[0].npc) {
                                val result = Result(
                                    lineupList = lineupList,
                                    monsterList = monsterList
                                )
                                val npcInfo = NpcInfo(
                                    result = result
                                )
                                npcInfoList.add(npcInfo)
                                lineupList = mutableListOf()
                                monsterList = mutableListOf()
                            }
                        }
                        //组装一个npc的数据
                        val exist =
                            lineupList.find { it.area == currentArea && it.npc == currentNpc && it.idx == currentTeam }
                        if (exist != null) {
                            val playerlist = exist.playerList.toMutableList()
                            playerlist.add(player)
                            exist.playerList = playerlist
                        } else {
                            val lineup = LineupList(
                                area = currentArea,
                                npc = currentNpc,
                                idx = currentTeam,
                            ).also {
                                it.playerList = mutableListOf(player)
                            }
                            lineupList.add(lineup)
                        }

                        //组装一个monsterlist数据
                        val existMonster =
                            monsterList.find { it.name == player.name }
                        val teamNum = currentTeam[0].toString().toInt()
                        if (existMonster != null) {
                            val lineupSet = existMonster.lineupSet.toMutableSet()
                            lineupSet.add(teamNum)
                            existMonster.lineupSet = lineupSet
                        } else {
                            val newMonsterList = MonsterList(
                                id = player.id,
                                name = player.name,
                                area = currentArea,
                                npc = currentNpc,
                                lineupSet = mutableSetOf(teamNum)
                            )
                            monsterList.add(newMonsterList)
                        }
                    }

                }
                val result = Result(
                    lineupList = lineupList,
                    monsterList = monsterList
                )
                val npcInfo = NpcInfo(
                    result = result
                )
                npcInfoList.add(npcInfo)
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return npcInfoList
        }

        fun getAllTeamName(context: Context): List<String> {
            val resultList: MutableList<String> = mutableListOf()
            try {
                val filesDir = context.filesDir // 获取应用的私有目录
                val teamsDir = File(filesDir, "excels") // 获取应用私有空间的 "teams" 文件夹
                val files = teamsDir.listFiles() // 获取 "teams" 文件夹下的所有文件
                for (file in files!!) {
                    if (file.isFile) {
                        // 获取文件名（去除扩展名）
                        val fileName = file.nameWithoutExtension
                        resultList.add(fileName)
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return resultList
        }

        fun writeAllNpcs(fileName: String, npcs: List<NpcInfo>, context: Context) {
            try {
                val gson = Gson()
                val filesDir = context.filesDir // 获取应用的私有目录
                val teamsDir = File(filesDir, "teams") // 获取应用私有空间的 "teams" 文件夹
                if (!teamsDir.exists()) {
                    teamsDir.mkdir() // 如果 "teams" 文件夹不存在，则创建该文件夹
                }
                val targetFile = File(teamsDir, fileName) // 构造目标文件路径

                // 写入数据到目标文件
                val outputStream = FileOutputStream(targetFile)
                val writer = OutputStreamWriter(outputStream)
                for (npc in npcs) {
                    val json = gson.toJson(npc)
                    writer.write(json)
                    writer.write("\n") // 每行数据之间用换行符分隔
                }
                writer.close() // 关闭输出流
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }


        fun getAllNpcs(fileName: String, context: Context): List<NpcInfo> {
            val resultList: MutableList<NpcInfo> = mutableListOf()
            try {
                val gson = Gson()
                val filesDir = context.filesDir // 获取应用的私有目录
                val targetFile = File(filesDir, "teams/$fileName") // 构造目标文件路径

                // 读取目标文件的内容
                val inputStream = FileInputStream(targetFile)
                val bufferedReader = BufferedReader(InputStreamReader(inputStream))
                var line = bufferedReader.readLine()
                while (line != null) {
                    val bean = gson.fromJson(line, NpcInfo::class.java)
                    resultList.add(bean)
                    line = bufferedReader.readLine()
                }
                inputStream.close() // 关闭输入流
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return resultList
        }

        // 复制输入流到输出流的函数
        private fun copyFile(inputStream: InputStream, outputStream: OutputStream) {
            inputStream.use { input ->
                outputStream.use { output ->
                    input.copyTo(output)
                }
            }
        }

        // 复制 assets 中的文件夹到应用私有空间中
        private fun copyAssetsFolder(context: Context, folderName: String) {
            val assets = context.assets // 获取应用的 assets 目录
            val filesDir = context.filesDir // 获取应用的私有目录

            // 创建用于保存复制后的文件的目标目录
            val targetDir = File(filesDir, folderName)
            if (!targetDir.exists()) {
                targetDir.mkdirs()
            }

            // 获取 assets 文件夹中指定文件夹下的所有文件列表
            val files = assets.list(folderName)
            files?.forEach { fileName ->
                val assetFilePath = "$folderName/$fileName"
                val targetFile = File(targetDir, fileName)

                // 如果目标文件已经存在，则跳过该文件
                if (targetFile.exists()) {
                    targetFile.delete()
                }

                // 打开 assets 文件并将其复制到目标文件中
                val input = assets.open(assetFilePath)
                val output = targetFile.outputStream()
                copyFile(input, output)
                Log.d("test", "copy file: $fileName")

                // 关闭输入和输出流
                input.close()
                output.close()
            }
        }

        // 在 Activity 或 Fragment 中调用该函数来复制 assets 中的 "teams" 文件夹到应用私有空间中
        fun copyTeamsFolderToPrivateSpace(context: Context) {
            try {
//                copyAssetsFolder(context, "teams")
                copyAssetsFolder(context, "excels")
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}